JDSL: The Data Structures Library In Java by Roberto Tamassia, Michael T. Goodrich, Luca Vismara, Mark Handy, Galina Shubina, Robert Cohen, Benoit Hudson, Ryan S. Baker, Natasha Gelfand, Ulrik Brandes Listing One package jdsl.graph.algo; import jdsl.core.api.*; import jdsl.core.ref.ArrayHeap; import jdsl.core.ref.IntegerComparator; import jdsl.graph.api.*; public abstract class IntegerDijkstraTemplate { // instance variables protected PriorityQueue pq_; protected InspectableGraph g_; protected Vertex source_; private final Integer ZERO = new Integer(0); private final Integer INFINITY = new Integer(Integer.MAX_VALUE); private final Object LOCATOR = new Object(); private final Object DISTANCE = new Object(); private final Object EDGE_TO_PARENT = new Object(); // abstract instance methods protected abstract int weight (Edge e); // instance methods that may be overridden for special applications protected void shortestPathFound (Vertex v, int vDist) { v.set(DISTANCE,new Integer(vDist)); } protected void vertexNotReachable (Vertex v) { v.set(DISTANCE,INFINITY); setEdgeToParent(v,Edge.NONE); } protected void edgeRelaxed (Vertex u, int uDist, Edge uv, int uvWeight, Vertex v, int vDist) { } protected boolean shouldContinue () { return true; } protected boolean isFinished (Vertex v) { return v.has(DISTANCE); } protected void setLocator (Vertex v, Locator vLoc) { v.set(LOCATOR,vLoc); } protected Locator getLocator (Vertex v) { return (Locator)v.get(LOCATOR); } protected void setEdgeToParent (Vertex v, Edge vEdge) { v.set(EDGE_TO_PARENT,vEdge); } protected EdgeIterator incidentEdges (Vertex v) { return g_.incidentEdges(v,EdgeDirection.OUT | EdgeDirection.UNDIR); } protected Vertex destination (Vertex origin, Edge e) { return g_.opposite(origin,e); } protected VertexIterator vertices () { return g_.vertices(); } protected PriorityQueue newPQ () { return new ArrayHeap(new IntegerComparator()); } // output instance methods public final boolean isReachable (Vertex v) { return v == source_ || v.has(EDGE_TO_PARENT) && v.get(EDGE_TO_PARENT) != Edge.NONE; } public final int distance (Vertex v) throws InvalidQueryException { try { return ((Integer)v.get(DISTANCE)).intValue(); } catch (InvalidAttributeException iae) { throw new InvalidQueryException(v+" has not been reached yet"); } } public Edge getEdgeToParent (Vertex v) throws InvalidQueryException { try { return (Edge)v.get(EDGE_TO_PARENT); } catch (InvalidAttributeException iae) { String s = (v == source_) ? " is the source vertex" : " has not been reached yet"; throw new InvalidQueryException(v+s); } } // instance methods composing the core of the algorithm public void init (InspectableGraph g, Vertex source) { g_ = g; source_ = source; pq_ = newPQ(); VertexIterator vi = vertices(); while (vi.hasNext()) { Vertex u = vi.nextVertex(); Integer uKey = (u == source_) ? ZERO : INFINITY; Locator uLoc = pq_.insert(uKey,u); setLocator(u,uLoc); } } protected final void runUntil () { while (!pq_.isEmpty() && shouldContinue()) doOneIteration(); } public final void doOneIteration () throws InvalidEdgeException { Integer minKey = (Integer)pq_.min().key(); // remove a vertex with minimum distance from the source Vertex u = (Vertex)pq_.removeMin(); if (minKey == INFINITY) vertexNotReachable(u); else { // the general case int uDist = minKey.intValue(); shortestPathFound(u,uDist); int maxEdgeWeight = INFINITY.intValue()-uDist-1; EdgeIterator ei = incidentEdges(u); while (ei.hasNext()) { // examine all the edges incident with u Edge uv = ei.nextEdge(); int uvWeight = weight(uv); if (uvWeight < 0 || uvWeight > maxEdgeWeight) throw new InvalidEdgeException ("The weight of "+uv+" is either negative or causing overflow"); Vertex v = destination(u,uv); Locator vLoc = getLocator(v); if (pq_.contains(vLoc)) { // v is not finished yet int vDist = ((Integer)vLoc.key()).intValue(); int vDistViaUV = uDist+uvWeight; if (vDistViaUV < vDist) { // relax pq_.replaceKey(vLoc,new Integer(vDistViaUV)); setEdgeToParent(v,uv); } edgeRelaxed(u,uDist,uv,uvWeight,v,vDist); } } } } public final void execute (InspectableGraph g, Vertex source) { init(g,source); runUntil(); } public void cleanup () { VertexIterator vi = vertices(); while (vi.hasNext()) { vi.nextVertex().destroy(LOCATOR); try { vi.vertex().destroy(EDGE_TO_PARENT); vi.vertex().destroy(DISTANCE); } catch (InvalidAttributeException iae) { } } } } // class IntegerDijkstraTemplate Listing Two package jdsl.graph.algo; import jdsl.core.api.*; import jdsl.core.ref.NodeSequence; import jdsl.graph.api.*; import jdsl.graph.ref.EdgeIteratorAdapter; public abstract class IntegerDijkstraPathfinder extends IntegerDijkstraTemplate { // instance variables private Vertex dest_; // overridden instance methods from IntegerDijkstraTemplate protected boolean shouldContinue () { return !isFinished(dest_); } // output instance methods public boolean pathExists () { return isFinished(dest_); } public EdgeIterator reportPath () throws InvalidQueryException { if (!pathExists()) throw new InvalidQueryException ("No path exists between "+source_+" and "+dest_); else { Sequence retval = new NodeSequence(); Vertex currVertex = dest_; while (currVertex != source_) { Edge currEdge = getEdgeToParent(currVertex); retval.insertFirst(currEdge); currVertex = g_.opposite(currVertex,currEdge); } return new EdgeIteratorAdapter(retval.elements()); } } // instance methods public final void execute (InspectableGraph g, Vertex source, Vertex dest) { dest_ = dest; init(g,source); if (source_ != dest_) runUntil(); } } // class IntegerDijkstraPathfinder Listing Three import jdsl.graph.api.*; import jdsl.graph.algo.IntegerDijkstraPathfinder; import support.*; public class FlightDijkstra extends IntegerDijkstraPathfinder { // instance variables private int startTime_; // overridden instance methods from IntegerDijkstraPathfinder protected int weight (Edge e) { // the flightspecs for the flight along edge e FlightSpecs eFS = (FlightSpecs)e.element(); int connectingTime = TimeTable.diff(eFS.departureTime(), startTime_+distance(g_.origin(e))); return connectingTime+eFS.flightDuration(); } protected EdgeIterator incidentEdges (Vertex v) { return g_.incidentEdges(v,EdgeDirection.OUT); } // instance methods public void execute (InspectableGraph g, Vertex source, Vertex dest, int startTime) { startTime_ = startTime; super.execute(g,source,dest); } } // class FlightDijkstra